/*
 * GccApplication1.c
 *
 * Created: 4/14/2015 10:24:10 AM
 *  Author: schussle
 */ 


#include <avr/io.h>
#include <avr/interrupt.h>
#define MOSI 3
#define SCK 5
#define SS 2

void usart_init();
void tcnt_init();
void segmentDisplay();
void execute(unsigned char cmd, unsigned char data);

int f;    // temperature in Fahrenheit
char first, second;

int main(void)
{
        DDRB = (1<<MOSI)|(1<<SCK)|(1<<SS);    // enable outputs for max7221 converter
        DDRD = 1;        // enable output of PD0 for testing
        DDRC = 0;        // enable PC0 for analog input
        int temp;        // to combine high and low converted values
        
        ADCSRA = 0x87;    // ADC enable with select prescaler of 64
        ADMUX = 0xC0;    // 1.1 V reference and ADC0 left justified
        
        usart_init();    // initialize USART for serial output
        tcnt_init();    // initialize tcnt1 timer
        
        while (1)
        {
            ADCSRA|=(1<<ADSC);                    // start conversion
            while ((ADCSRA&(1<<ADIF))==0);        // wait for conversion to finish
            temp = ADCL + (ADCH * 256);            // combine converted number into single integer
            f = ((temp * 1.1)/1024)*180 + 32;    // convert read value into Fahrenheit
        }
}

void segmentDisplay()
{
    SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);    // enable SPI as master
    
    execute(0x09,0b00000011);    // enable decoding for digits 0,1
    
    execute(0x0B,0x02);        // display digits 0,1 (changed from 0x02)
    execute(0x0C,0x01);        // turn on the chip
    execute(0x01,first);    // display first digit (0)
    execute(0x02,second);    // display second digit (1)
}

void execute(unsigned char cmd, unsigned char data)
{
    PORTB &= ~(1<<SS); // initialize the packet by pulling SS low
    
    SPDR = cmd;    // start command transmission
    while(!(SPSR & (1<<SPIF)));    // wait for transfer to finish
    
    SPDR = data;    // start data transmission
    while(!(SPSR & (1<<SPIF)));    // wait for transfer to finish
    
    PORTB |= (1<<SS);    // terminate packet by pulling SS high
}

void usart_send (unsigned char ch)
{
    while(! (UCSR0A & (1<<UDRE0)));    // wait until ready to send
    UDR0 = ch;                        // send value over serial
}

void usart_init()
{
    UCSR0B = 0x08;    // enable transmitter
    UCSR0C = 0x06;    // enable 8-bit character size
    UBRR0L = 0x33;    // set baud rate
}

void tcnt_init()
{
    /* TIMER1 Delays
    1s = 0x85EE
    0.5s = 0xC2F7
    0.25s = 0xE17C
    125ms = 0xF0BE
    63ms = 0xF85F */

    TCNT1 = 0x85EE;    // 1s delay
    TCCR1A = 0x00;    // WGM = 0 for normal mode
    TCCR1B = 0x04;    // Normal mode, prescaler 256
    TIMSK1 = 0x01;    // enable interrupt on timer1 overflow for sending temperature over serial terminal
    sei();            // enable global interrupts
}

ISR (TIMER1_OVF_vect)
{
    char output[3];
    PORTD = PORTD ^ 1;        // toggle test PD0 led    
    itoa (f,output,10);        // convert temperature to string for USART output
    switch(output[0])
    {
        case '0':    first=0x00;
                    break;
        case '1':    first=0x01;
                    break;
        case '2':    first=0x02;
                    break;
        case '3':    first=0x03;
                    break;
        case '4':    first=0x04;
                    break;
        case '5':    first=0x05;
                    break;
        case '6':    first=0x06;
                    break;
        case '7':    first=0x07;
                    break;
        case '8':    first=0x08;
                    break;
        case '9':    first=0x09;
                    break;
        default:    first=0x00;
                    break;
    }
    switch(output[1])
    {
        case '0':    second=0x00;
                    break;
        case '1':    second=0x01;
                    break;
        case '2':    second=0x02;
                    break;
        case '3':    second=0x03;
                    break;
        case '4':    second=0x04;
                    break;
        case '5':    second=0x05;
                    break;
        case '6':    second=0x06;
                    break;
        case '7':    second=0x07;
                    break;
        case '8':    second=0x08;
                    break;
        case '9':    second=0x09;
                    break;
        default:    second=0x00;
                    break;
    }

    segmentDisplay();        // output Fahrenheit temperature to seven segment displays
    usart_send(output[0]);    // send first digit of Fahrenheit temperature over serial
    usart_send(output[1]);    // send second digit of Fahrenheit temperature over serial
    usart_send('\n');        // send new line over serial
    TCNT1=0x85EE;            // reset TCNT for 1s delay
}